package cn.client.ui.view.main.user

import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cn.client.data.remoteData.bean.BaseResp
import cn.client.data.remoteData.bean.UserBasicInfo
import cn.client.data.remoteData.bean.UserInfo
import cn.client.data.localData.dao.UserDao
import cn.client.data.localData.entity.UserEntity
import cn.client.data.remoteData.repository.UserRepository
import cn.client.data.userStateManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject

/**
 * 用户信息ViewModel
 */
@HiltViewModel
class UserInfoViewModel @Inject constructor(
    private val repository: UserRepository,
    private val userDao: UserDao
) : ViewModel() {

    /**
     * 事件管道
     */
    private val _pageEvents = Channel<PageEvent>(Channel.BUFFERED)

    /**
     * 可观察事件数据流
     */
    val pageEvents = _pageEvents.receiveAsFlow()

    /**
     * 可变状态
     */
    var pageStates by mutableStateOf(PageState())
        private set

    // 使用MutableStateFlow来存储uid
    private val _userId = MutableStateFlow<Int>(-1)
    val userId: StateFlow<Int> = _userId.asStateFlow()

    // 加载状态
    private val _isLoading = MutableStateFlow<Boolean>(false)
    val isLoading: StateFlow<Boolean> = _isLoading

    /**
     * 收集意图
     */
    fun dispatch(intent: PageIntent) {
        when (intent) {
            is PageIntent.GetUserInfo -> getUserInfo(intent.uid)
            is PageIntent.EditUserInfo -> editUserInfo(
                intent.uid,
                intent.uname,
                intent.gender,
                intent.birthday,
                intent.area
            )
            is PageIntent.SignOut -> signOut(intent.uid)
            is PageIntent.GetUser -> getUser(intent.msg)
            is PageIntent.UpAvatar -> upAvatar(intent.uid, intent.file)
            else -> {
                Unit
            }
        }
    }



    // 意图：获取用户信息
    private fun getUserInfo(uid: Int) {
        viewModelScope.launch {
            try {
                val res = repository.userInfo(uid)
                if (res.code == 200) {
                    pageStates = res.data?.let { it ->
                        pageStates.copy(
                            uid = it.uid,
                            uname = it.uname,
                            gender = it.gender,
                            email = it.email,
                            area = it.area,
                            birthday = it.birthday,
                            avatar = it.avatar,
                            background = it.background
                        )
                    }!!
                } else {
                    val err = res.msg
                    _pageEvents.send(PageEvent.Error(err))
                    Log.d("UserInfoViewModel", "获取失败：$err")
                }
            } catch (e: Exception) {
                val errors = PageEvent.Error(e.localizedMessage ?: "UnKnown Error")
                Log.d("UserInfoViewModel", "getUserInfo 方法发生异常：$e uid: $uid")
                _pageEvents.send(errors)
            }
        }
    }


    // 意图：修改用户信息
    private fun editUserInfo(
        uid: Int,
        uname: String?,
        gander: Int,
        birthday: Long?,
        area: String?
    ) {
        viewModelScope.launch {
            val userBasicInfo = UserBasicInfo(uid, uname, gander, birthday, area)
            try {
                val res = repository.uploadUserBasicInfo(userBasicInfo)
                if (res.code == 200) {
                    _pageEvents.send(PageEvent.EditUserInfo(res))
                } else {
                    val err = res.msg
                    _pageEvents.send(PageEvent.Error(err))
                    Log.d("UserInfoViewModel", "修改失败：$err")
                }
            } catch (e: Exception) {
                val errors = PageEvent.Error(e.localizedMessage ?: "UnKnown Error")
                Log.d("UserInfoViewModel", "editUserInfo 方法发生异常：$e")
                _pageEvents.send(errors)
            }
        }
    }

    // 意图：退出登录
    private fun signOut(uid: Int) {
        viewModelScope.launch {
            try {
                val res = repository.logOut(uid)
                if (res.code == 200) {
                    userDao.delete(UserEntity(uid = uid))
                    _pageEvents.send(PageEvent.Out(res.msg))
                } else {
                    _pageEvents.send(PageEvent.Error(res.msg))
                }
            } catch (e: Exception) {
                val errors = PageEvent.Error(e.localizedMessage ?: "UnKnown Error")
                Log.d("UserInfoViewModel", "signOut方法发生异常：$e")
                _pageEvents.send(errors)
            }
        }
    }


    // 查询本地缓存
    private fun getUser(msg: String){
        Log.d("getUser","消息：$msg")
        viewModelScope.launch {
            // 显示加载动画
            _isLoading.value = true
            userDao.getUser().catch { e ->
                Log.d("UserInfoViewModel", "getUser方法异常：$e")
                // 隐藏加载动画
                _isLoading.value = false
                _pageEvents.send(PageEvent.GetErr("没有查询到缓存：$e"))
            }.collect { it ->
                if (it != null) {
                    _pageEvents.send(PageEvent.UserRes(uid = it.uid))
                    _userId.value = it.uid
                    userStateManager.setUserId(newId =  it.uid)
                    // 隐藏加载动画
                    _isLoading.value = false
                } else {
                    // 隐藏加载动画
                    _isLoading.value = false
                    _pageEvents.send(PageEvent.GetErr("查询失败"))
                }
            }
        }
    }

    // 上传头像
    private fun upAvatar(uid: Int, file: File){
        viewModelScope.launch {
            try {
                val res = repository.uploadAvatar(file=file, uid = uid)
                if (res.code == 200) {
                    _pageEvents.send(PageEvent.Success(res.msg))
                }else{
                    _pageEvents.send(PageEvent.Error(res.msg))
                }
            } catch (e: Exception) {
                val errors = PageEvent.Error(e.localizedMessage ?: "UnKnown Error")
                Log.d("UserInfoViewModel", "upAvatar 方法发生异常：$e")
                _pageEvents.send(errors)
            }
        }
    }

    /**
     * 意图集
     */
    sealed class PageIntent
    {
        data class GetUser(val msg: String) : PageIntent()  // 查询本地缓存
        data class GetUserInfo(val uid: Int) : PageIntent()
        data class SignOut(val uid: Int) : PageIntent()
        data class UpAvatar(val uid: Int, val file: File): PageIntent()


        // 修改用户信息
        data class EditUserInfo(
            val uid: Int,
            val uname: String?,
            val gender: Int,
            val birthday: Long?,
            val area: String?
        ) : PageIntent()
    }

    /**
     * 事件集
     */
    sealed class PageEvent {
        object Idle : PageEvent() // 空闲
        data class UserInfoRes(val res: BaseResp<UserInfo>) : PageEvent()   // 获取的用户信息
        data class EditUserInfo(val res: BaseResp<Any>) : PageEvent()
        data class Success(val success: String) : PageEvent()
        data class UserRes(val uid: Int) : PageEvent()  // 本地缓存
        data class GetErr(val msg: String): PageEvent() // 获取本地缓存失败
        data class Out(val res: String): PageEvent()
        data class Error(val error: String) : PageEvent()   // 错误信息
    }

    /**
     * 状态集
     */
    data class PageState(
        val uid: Int = -1,
        val uname: String = "",
        val gender: Int? = -1,
        val email: String? = "",
        val area: String? = "",
        val birthday: Long? = 0L,
        val avatar: String = "",
        val background: String = ""
    )

}